#include <stdio.h>

#include "MyRTPSession.h"
#include "MyTcpTransmitter.h"

#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string>

std::string StringToHexString(std::string str)
{
    std::string output;
    char temp[8];
    for (int i = 0; i < int(str.length()); ++i)
    {
        sprintf(temp, "%.2x", *(uint8_t *)(str.data() + i));
        output.append(temp, 2);
    }
    return output;
}

int threadRtpRecv()
{
    printf("threadRtpRecv\n");

    bool RecvRun = true;

    MyRTPSession sess;
    // RTPSession sess;
    int status;
    struct timeval struc_start, struc_end;
    long start_time, end_time;
    long dif_time = 0;
    int socket_statsus = 1;

    // jrtp UDP/TCP
    RTPSessionParams sessparams;
    sessparams.SetOwnTimestampUnit(1.0 / 8000.0);
    sessparams.SetAcceptOwnPackets(true);
    sessparams.SetSourceTimeoutMultiplier(100);

    MyTCPTransmitter tcpTransmitter("Transmitter_Server");
    RTPUDPv4TransmissionParams udpTansparams;
    int nRet = 0;
    uint16_t listenPort = 50000;

    printf("start create tcp listerner socket\n");
    SocketType listener = socket(AF_INET, SOCK_STREAM, 0);
    if (listener == -1) //if (listener == RTPSOCKERR)
    {
        printf("Can't create listener socket\n");
        return -1;
    }
    printf("create tcp listerner socket [%d]\n", listener);

    struct sockaddr_in serverAddr;
    memset(&serverAddr, 0, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(listenPort); //监听50000端口

    printf("listerner socket [%d] start bind [%d]\n", listener, listenPort);
    nRet = bind(listener, (sockaddr *)&serverAddr, sizeof(serverAddr));
    if (nRet != 0)
    {
        close(listener);
        printf("listerner socket [%d] Can't bind listener socket\n", listener);
        return -1;
    }
    printf("listerner socket [%d] start listener %d\n", listener, listenPort);
    nRet = listen(listener, 1); // 只接入一个连接
    if (nRet < 0)
    {
        close(listener);
        printf("listerner socket [%d] listener socket error\n", listener);
        return -1;
    }

    struct sockaddr_in clientAddr;
    unsigned int nLen = sizeof(sockaddr_in);
    printf("listerner socket [%d] start accept %d\n", listener, listenPort);
    SocketType client = accept(listener, (sockaddr *)&clientAddr, &nLen);
    if (client < 0)
    {
        printf("listerner socket [%d] accept error\n", listener);
        close(listener);
        return -1;
    }

    printf("input [SOCKET: %d, IP：%s,  PORT：%d]\n", client, inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));

    status = tcpTransmitter.Init(false); // TODO 研究为什么不能传true，否则会报错
    if (status < 0)
    {
        close(client);
        close(listener);
        printf("rtp over tcp tcpTransmitter.Init %s\n", RTPGetErrorString(status).c_str());
        return -1;
    }
    status = tcpTransmitter.Create(65535, NULL);
    if (status < 0)
    {
        close(client);
        close(listener);
        printf("rtp over tcp tcpTransmitter.Create %s\n", RTPGetErrorString(status).c_str());
        return -1;
    }
    status = sess.Create(sessparams, &tcpTransmitter);
    if (status < 0)
    {
        //TODO 删除创建的对象
        close(client);
        close(listener);
        printf("rtp over tcp receive create %s\n", RTPGetErrorString(status).c_str());
        return -1;
    }
    sess.AddDestination(RTPTCPAddress(client));

    printf("socket_statsus %d\n", socket_statsus);
    printf("receive rtp port = %d\n", listenPort);

    RTPTime delay(0, 8000);
    RTPPacket *pPacket;
    bool isFirst = false;
    while (RecvRun)
    {
        sess.BeginDataAccess();
        if (sess.GotoFirstSourceWithData())
        {
            do
            {
                while ((pPacket = sess.GetNextPacket()) != NULL)
                {
                    uint32_t sequenceNumber = pPacket->GetSequenceNumber();
                    uint32_t ssrc = pPacket->GetSSRC();
                    bool marker = pPacket->HasMarker();
                    uint8_t *RtpBuffer = pPacket->GetPayloadData();
                    size_t RtpBufferSize = pPacket->GetPayloadLength();
                    if (isFirst)
                    {
                        printf("GetH246FromPs[%d]=>%s\n", RtpBufferSize, StringToHexString(std::string((char *)RtpBuffer, RtpBufferSize).substr(0, 100)).c_str());
                    }
                    printf("writeRtp[%d:%d,%s,%d]\n", sequenceNumber, ssrc, marker ? "true" : "false", RtpBufferSize);
                    if (marker)
                        isFirst = true;
                    else
                        isFirst = false;

                    sess.DeletePacket(pPacket);
                }
            } while (sess.GotoNextSourceWithData());
        }
        sess.EndDataAccess();

#ifndef RTP_SUPPORT_THREAD
        status = sess.Poll();
        if (status < 0)
        {
            printf("sess.Poll %s", RTPGetErrorString(status).c_str());
        }
#endif // RTP_SUPPORT_THREAD

        RTPTime::Wait(delay);
    }

    printf("BYEDestroy\n");
    sess.BYEDestroy(RTPTime(10, 0), 0, 0);

    return 0;
}

int main(int argn, char **argv)
{
    threadRtpRecv();
    printf("Hello World!\n");
    return 0;
}